package ongd.negocio.gestion;

import java.util.List;
import java.util.Properties;
import javax.mail.Message.RecipientType;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import ongd.negocio.sesion.ControladorSesion;
import ongd.servicios.persistencia.ControladorPersistencia;

/**
 * Clase que realizará todas las operaciones referentes a la configuración
 * de la aplicación.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 */
public class ControladorConfiguracion {

    /**
     * Objeto del tipo controlador persistencia que nos servirá para crear 
     * las instancias de las diferentes entidades.
     */
    private ControladorPersistencia contP;
    /**
     * Objeto del tipo controlador sesion que nos servirá para sabre 
     * en que sesion estamos.
     */
    private ControladorSesion contSesion;
    /**
     * Objeto de tipo properties que va a contener los datos del email.
     */
    private Properties propMail;
    /**
     * Objeto de tipo Session que será la sesion iniciada con la cuenta de
     * correo que será la uqe envie los emails.
     */
    private Session sesionMail = null;
    /**
     * Objeto de tipo configuración que va a contener datos de configuración
     * de la aplicación.
     */
    private Configuracion datosEmail;

    /**
     * Constructor de la clase.
     * @param contP controlador Persistencia
     * @param contSesion sesión en la que estamos
     */
    public ControladorConfiguracion(ControladorPersistencia contP, ControladorSesion contSesion) {
        this.contP = contP;
        this.contSesion = contSesion;
        this.propMail = new Properties();
        datosEmail = new Configuracion();
    }

    /**
     * Método que devuelve los datos del email existente en la configuración.
     * @return configuracion
     */
    private Configuracion cargarDatosEmail() {
        Configuracion d = new Configuracion();
        List<Configuracion> configuraciones = (List<Configuracion>) contP.obtenerEntidades(Configuracion.class);
        if (!configuraciones.isEmpty()) {
            //Miraré que tenga todos los campos
            d = configuraciones.get(0);
        }
        return d;
    }

    /**
     * Método que envia una alerta en función de la direccion, el asunto y 
     * el mensaje.
     * @param vctDirecciones Direcciones a las que se envia la alerta
     * @param strAsunto Asunto de la alerta
     * @param strMensaje Mensaje que va a contener
     */
    public void enviarAlerta(List<String> vctDirecciones, String strAsunto, String strMensaje) {
        //Obtengo la lista de direcciones a donde tengo que mandar el mail
        datosEmail = cargarDatosEmail();
        inicializarEnvioMail();
        enviarMail(vctDirecciones, strAsunto, strMensaje);
    }

    /**
     * Método que inicializa las variables para el envio de un email.
     */
    private void inicializarEnvioMail() {
        if (datosEmail.getMailHostSMTP() != null && datosEmail.getMailPuertoSMTP() != null
                && datosEmail.getMailUsuario() != null && datosEmail.getMailPassword() != null) {
            //Nombre del Host de correo, es smtp.gmail.com
            this.propMail.setProperty("mail.smtp.host", datosEmail.getMailHostSMTP());
            //TLS si está disponible
            this.propMail.setProperty("mail.smtp.starttls.enable", "true");
            //Puerto de gmail para envio de correos
            this.propMail.setProperty("mail.smtp.port", datosEmail.getMailPuertoSMTP());
            //Nombre del usuario
            this.propMail.setProperty("mail.smtp.user", datosEmail.getMailUsuario());
            //Si requiere o no usuario y password para conectarse
            this.propMail.setProperty("mail.smtp.auth", "true");
            //Obtenemos la instancia de la sesión
            this.sesionMail = Session.getInstance(this.propMail, null);
            //Pongo esto para obtener más información por pantalla de lo que sucede.
            sesionMail.setDebug(true);
        }
    }

    /**
     * Método que envia una email.
     * @param vctDirecciones Direcciones a las que enviar el email
     * @param strAsunto Asunto del email
     * @param strMensaje Contenido del mensaje
     */
    private synchronized void enviarMail(List<String> vctDirecciones, String strAsunto, String strMensaje) {
        if (!vctDirecciones.isEmpty()) {
            int intIntentos = 0;
            while (intIntentos++ < 5) {
                try {
                    MimeMessage mensajeMail = new MimeMessage(this.sesionMail);
                    //Quien envia el correo
                    mensajeMail.setFrom(new InternetAddress(datosEmail.getMailDireccion()));
                    //A quien va dirigido, recorró la lista de direcciones.
                    for (int i = 0; i < vctDirecciones.size(); i++) {
                        mensajeMail.addRecipient(RecipientType.TO, new InternetAddress(vctDirecciones.get(i)));
                    }
                    //Pongo el asunto del mensaje
                    mensajeMail.setSubject(strAsunto);
                    //Pongo el texto
                    mensajeMail.setText(strMensaje);
                    //Envio el mensaje
                    Transport trsMail = this.sesionMail.getTransport("smtp");
                    //Establezco la conexión, dando el nombre de usuario y el password.
                    trsMail.connect(datosEmail.getMailUsuario(), datosEmail.getMailPassword());
                    //Enviamos el mensaje
                    trsMail.sendMessage(mensajeMail, mensajeMail.getAllRecipients());
                    //Cerramos la conexion
                    trsMail.close();
                    intIntentos = 100;
                } catch (Exception ex) {
                }
            }
        }
    }
    
   /**
     * Método que devuelve un objeto del tipo ControladorPersistencia.
     * @return contP
     * @see #setContP
     */
    public ControladorPersistencia getContP() {
        return contP;
    }

    /**
     * Método que establece un objeto del tipo ControladorPersistencia.
     * @param contP Nuevo valor de la variable
     * @see #getContP
     */
    public void setContP(ControladorPersistencia contP) {
        this.contP = contP;
    }

    /**
     * Método que devuelve un objeto del tipo ControladorSesion.
     * @return contSesion
     * @see #setContSesion
     */
    public ControladorSesion getContSesion() {
        return contSesion;
    }

    /**
     * Método que establece un objeto del tipo ControladorSesion.
     * @param contSesion Nuevo valor de la variable
     * @see #getContSesion
     */
    public void setContSesion(ControladorSesion contSesion) {
        this.contSesion = contSesion;
    }   

    /**
     * Método que devuelve el valor de la variable datosEmail.
     * @return datosEmail
     * @see #setDatosEmail
     */
    public Configuracion getDatosEmail() {
        return datosEmail;
    }

    /**
     * Método que establece el valor de la variable datosEmail.
     * @param datosEmail Nuevo valor de la variable
     * @see #getDatosEmail
     */
    public void setDatosEmail(Configuracion datosEmail) {
        this.datosEmail = datosEmail;
    }

    /**
     * Método que devuelve el valor de la variable propMail.
     * @return propMail
     * @see #setPropMail
     */
    public Properties getPropMail() {
        return propMail;
    }

    /**
     * Método establece el valor de la variable propMail.
     * @param propMail Nuevo valor de la variable
     * @see #getPropMail
     */
    public void setPropMail(Properties propMail) {
        this.propMail = propMail;
    }

    /**
     * Método que devuelve el valor de la variable sesionMail.
     * @return sesionMail
     * @see #setSesionMail
     */
    public Session getSesionMail() {
        return sesionMail;
    }

    /**
     * Método que establece el valor de la variable sesionMail.
     * @param sesionMail Nuevo valor de la variable
     * @see #getSesionMail
     */
    public void setSesionMail(Session sesionMail) {
        this.sesionMail = sesionMail;
    }
}
